
#ifndef __USKELETON_BUILDER_H__
#define __USKELETON_BUILDER_H__

#include "mesh.h"
#include "gskeleton.h"
#include "wavefront.h"

#include <vector>
#include <list>
#include <stack>

using namespace std;

struct Info {
   Info() {}
   Info(const Info &I) {
      *this = I;
   }
   const Info& operator=(const Info &I) {
      plc = I.plc;
      pc = I.pc;
      return *this;
   }
   vector<int>     plc;
   vector<int>     pc;
};

class AutoSkelBuilder {
   
public:
   AutoSkelBuilder();
   ~AutoSkelBuilder();
   AutoSkelBuilder(Mesh *);
   
   GSkeleton *create(const vector<Vertex_handle> &seeds);
   
   GSkeleton *create_usingwavefronts(const vector<Vertex_handle> &seeds);
   
private:
   /// entre todas las distancias generadas por los seeds, esta funcion
   /// particionada la malla en regiones separadas por su lejania a un
   /// determinado seed
   void setMinDistance(const vector<Vertex_handle> &seeds);
   
   void genIsoRings();
   
   void allocatingWArrays();
   void setDistances(int idsource);
   void computeUpperBounds();
   
   /// wave fronts
   void computeUsingWaveFronts();
   void ExpandingTree(int idwf, int lastwavefront, vector<Point3> &centroides);
   void closing_nodes(int nodeid, int idwf);
protected:
   Mesh                                *mesh; // the mesh to be processed
   
   vector<vector<Number> >             distancesList; // distances list: mesh_vertices x seeds
   float                               intervalEquival;  
   int                                 nIsoRings;
   int                                 nseeds; // number of seeds
   
   typedef pair<int, int>              bone;
   typedef std::list<Vertex_handle>    ring; // 
   map<bone, ring>                     bonesl; // usar ponteiro a lista de handles !!!!!!
   
   vector<vector<int> >                graph; // A table that represents the squeleton's connectivity 
   typedef list<Vertex_handle>         Ring; // A set of vertices
   multimap<int,Ring>                  IsoRings; // 
   
   vector<Info>                        parentNode;
   vector<float>                       upper_bound; // ate quando a distancia de um vertice a fonte ordered_source[i] e' valida
   vector<float>                       costsl; 
   vector<vector<int> >                joinseedsl; // for each join there is a variable size list of idseeds
   
   vector<Point3>                      joints;
   
   /// 
   vector<OpenList>                    openlists;
   vector<WaveFront>                   wavefronts;
   Vector3                             sumVerticesBand;
   int                                 numVerticesBand;
   int                                 currentBand;
   vector<int>                         parentband;
   
   float                               bandbound;        // limite para a largura da faixa
   float                               activebandbound;
   bool                                bandhasanewvertex;
};

#endif
